home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / DEMOS / BURN11.ZIP / BURN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-05-19  |  8.8 KB  |  394 lines

  1. {$A+,B-,D+,E+,F-,G+,I-,L+,N+,O-,P+,Q-,R-,S-,T-,V-,X+,Y+}
  2. {$M 16384,0,655360}
  3.  
  4. {
  5.  
  6. Hi guys, try this, use it in your code, but please credit
  7.  
  8. Frank Jan Sorensen Alias:Frank Patxi (fjs@lab.jt.dk) for the
  9. fireroutine.
  10.  
  11. }
  12.  
  13. {
  14.  
  15. Hi again, guys!
  16.  
  17. If you use this code, please also credit me, Joachim Fenkes, 'cause I added
  18. the following speedups:
  19.  
  20.   -Replaced one tiny loop with a faster Move(...) (not much speedup)
  21.   -Wrote the main display loop in 100% assembler, including a faster random
  22.    number generator (the RNG is only a more or less optimized version of
  23.    Borland's generator (see MEGARAND.ASM), but with the advantage of the
  24.    ultimate crash if you call it normally :-)
  25.   -Changed version number into 1.10 (this isn't a speedup, but necessary :-)
  26.  
  27. }
  28.  
  29.  
  30. Program Burn;
  31. uses
  32.   Dos,Crt;
  33.  
  34. Const
  35.   RootRand     =  20;   { Max/Min decrease of the root of the flames }
  36.   Decay        =  10;   { How far should the flames go up on the screen? }
  37.                         { This MUST be positive - JF }
  38.   MinY         = 100;   { Startingline of the flame routine.
  39.                           (should be adjusted along with MinY above) }
  40.   Smooth       =   1;   { How descrete can the flames be?}
  41.   MinFire      =  50;   { limit between the "starting to burn" and
  42.                           the "is burning" routines }
  43.   XStart       = 90;   { Startingpos on the screen }
  44.   XEnd         = 210;   { Guess! }
  45.   Width        = XEnd-XStart; {Well- }
  46.   MaxColor     = 110;   { Constant for the MakePal procedure }
  47.   FireIncrease : Byte =   3;  {3 = Wood, 90 = Gazolin}
  48.  
  49. Var
  50.   Scr : Array[0..199,0..319] Of Byte Absolute $A000:$0000;
  51.  
  52. Type
  53.   ColorValue     = record
  54.                      R, G, B : byte;
  55.                    end;
  56.   VGAPaletteType = array[0..255] of ColorValue;
  57.  
  58. procedure FastRand; external; { The famous mega-fast Randommer! }
  59. {$L MEGARAND}
  60.  
  61. procedure ReadPal(var Pal);
  62. var
  63.   K    : VGAPaletteType Absolute Pal;
  64.   Regs : Registers;
  65. begin
  66.   with Regs do
  67.   begin
  68.     AX := $1017;
  69.     BX := 0;
  70.     CX := 256;
  71.     ES := Seg(K);
  72.     DX := Ofs(K);
  73.     Repeat Until Port[$03DA] And $08 = $08; {Wait for rescan}
  74.     Intr($10,Regs);
  75.   end;
  76. end;
  77.  
  78. procedure WritePal(var Pal);
  79. Var
  80.   K : VGAPaletteType Absolute Pal;
  81.   Regs : Registers;
  82. begin
  83.   with Regs do
  84.   begin
  85.     AX := $1012;
  86.     BX := 0;
  87.     CX := 256;
  88.     ES := Seg(K);
  89.     DX := Ofs(K);
  90.     Repeat Until Port[$03DA] And $08 = $08; {Wait for rescan}
  91.     Intr($10,Regs);
  92.   end;
  93. end;
  94.  
  95. Procedure Hsi2Rgb(H, S, I : Real; var C : ColorValue);
  96. {Convert (Hue, Saturation, Intensity) -> (RGB)}
  97. var
  98.   T : Real;
  99.   Rv, Gv, Bv : Real;
  100. begin
  101.   T := H;
  102.   Rv := 1 + S * Sin(T - 2 * Pi / 3);
  103.   Gv := 1 + S * Sin(T);
  104.   Bv := 1 + S * Sin(T + 2 * Pi / 3);
  105.   T := 63.999 * I / 2;
  106.   with C do
  107.   begin
  108.     R := trunc(Rv * T);
  109.     G := trunc(Gv * T);
  110.     B := trunc(Bv * T);
  111.   end;
  112. end; { Hsi2Rgb }
  113.  
  114. { Faster put'n get pixel routines!  }
  115.  
  116. procedure put(x,y : integer; c : byte); assembler;
  117. { Written by Matt Sottile }
  118.  asm
  119.   mov ax,y
  120.   mov di,ax
  121.   shl ax,8
  122.   shl di,6
  123.   add di,ax
  124.   add di,x
  125.   mov ax,0a000h
  126.   mov es,ax
  127.   mov al,c
  128.   mov es:[di],al
  129.  end;
  130.  
  131. Function get(x,y : integer):byte; assembler;
  132. { Put Modified by me }
  133. asm
  134.   mov ax,y
  135.   mov bx,ax
  136.   shl ax,8
  137.   shl bx,6
  138.   add bx,ax
  139.   add bx,x
  140.   mov ax,0a000h
  141.   mov es,ax
  142.   mov al,es:[bx]
  143. end;
  144.  
  145. Procedure MakePal;
  146. Var
  147.   I : Byte;
  148.   Pal   : VGAPaletteType;
  149.  
  150. begin
  151.   FillChar(Pal,SizeOf(Pal),0);
  152.   For I:=1 To MaxColor Do
  153.     HSI2RGB(4.6-1.5*I/MaxColor,I/MaxColor,I/MaxColor,Pal[I]);
  154.   For I:=MaxColor To 255 Do
  155.   begin
  156.     Pal[I]:=Pal[I-1];
  157.     With Pal[I] Do
  158.     begin
  159.       If R<63 Then Inc(R);
  160.       If R<63 Then Inc(R);
  161.       If (I Mod 2=0) And (G<53)  Then Inc(G);
  162.       If (I Mod 2=0) And (B<63) Then Inc(B);
  163.     end;
  164.   end;
  165.  
  166.   WritePal(Pal);
  167.  
  168. end;
  169.  
  170.  
  171. Function Rand(R:Integer):Integer;{ Return a random number between -R And R}
  172. begin
  173.   Rand:=Random(R*2+1)-R;
  174. end;
  175.  
  176. Procedure Help;
  177. Var
  178.   Mode : Byte;
  179.   R    : Registers;
  180. begin
  181.   R.Ax:=$0F00;
  182.   Intr($10,R);
  183.   Mode:=R.Al;
  184.   R.Ax:=$0003;  {TextMode}
  185.   Intr($10,R);
  186.  
  187.   ClrScr;
  188.   WriteLn('Burn version 1.10');
  189.   WriteLn;
  190.   WriteLn('Light''n''play');
  191.   WriteLn;
  192.   WriteLn('Keys : ');
  193.   WriteLn('<space> : Throw in a match');
  194.   WriteLn('<W>     : Water');
  195.   WriteLn('<+>     : Increase intensity');
  196.   WriteLn('<->     : Decrease intensity');
  197.   WriteLn('<C>     : Initialize fire');
  198.   WriteLn('<1>..<9>: Burnability (1=Wood, 9=Gaz)');
  199.   WriteLn('<?>     : This help');
  200.   WriteLn;
  201.   Write('Hit any key kid >');
  202.   ReadKey;
  203.   R.Ax:=$0000+Mode;
  204.   Intr($10,R);
  205.   If Mode = $13 Then MakePal;
  206. end;
  207.  
  208. Var
  209.   FlameArray : Array[XStart..XEnd] Of Byte;
  210.   LastMode : Byte;
  211.   I,J : Integer;
  212.   X,P : Integer;
  213.   MoreFire,
  214.   V   : Integer;
  215.   R   : Registers;
  216.   Ch  : Char;
  217. begin
  218.  
  219.   Help;
  220.   RandomIze;
  221.   R.Ax:=$0F00;
  222.   Intr($10,R);
  223.   LastMode:=R.Al;
  224.   R.Ax:=$0013;
  225.   Intr($10,R);
  226.  
  227.   MoreFire:=1;
  228.   MakePal;
  229.  
  230. {
  231.   (* Use this if you want to view the palette *)
  232.   For I:=0 To 255 Do
  233.   For J:=0 To 20 Do
  234.     Put(I,J,I);
  235.   ReadKey;
  236. }
  237.  
  238.   { Initialize FlameArray }
  239.   For I:=XStart To XEnd Do
  240.     FlameArray[I]:=0;
  241.  
  242.   FillChar(Scr,SizeOf(Scr),0); { Clear Screen }
  243.  
  244.   repeat
  245.     If KeyPressed Then Ch:=ReadKey Else Ch:='.'; {'.' = Nothing (Dummy)}
  246.  
  247.     While KeyPressed Do ReadKey;  { Empty Keyboard buffer }
  248.  
  249.     { Put the values from FlameArray on the bottom line of the screen }
  250.     Move(FlameArray, Scr[199, XStart], Width+1);
  251.  
  252.     { This loop makes the actual flames }
  253.  
  254.     { Here comes my assembler code - JF }
  255.  
  256.     { There's still a little bug in the code: When you have started the fire,
  257.       some pixels near the upper left corner of the screen dance around. }
  258.  
  259.     asm
  260.        cld
  261.        push DS
  262.        mov AX, 0A000h
  263.        mov ES, AX
  264.        mov DS, AX
  265.        mov AX, MinY*320+XStart
  266.        mov SI, MinY*320+XStart
  267.        mov DI, MinY*320+XStart-320
  268.        mov CX, 200-MinY
  269. @@1:
  270.          push CX
  271.          mov CX, Width+1
  272. @@2:
  273.            lodsb
  274.            cmp AL, Decay
  275.            jb  @@3
  276.            cmp CX, 2
  277.            jb  @@3
  278.            cmp CX, Width-1
  279.            ja  @@3
  280.            push CX
  281.            push AX
  282.            mov BX, 3
  283.            call FastRand
  284.            dec AX
  285.            push AX
  286.            mov BX, Decay
  287.            call FastRand
  288.            pop DX
  289.            pop CX
  290.            sub CL, AL
  291.            mov AL, CL
  292.            sub DI, DX
  293.            stosb
  294.            add DI, DX
  295.            pop CX
  296.            loop @@2
  297.  
  298.          add SI, 319-Width
  299.          mov DI, SI
  300.          sub DI, 320
  301.          pop CX
  302.          loop @@1
  303.  
  304.        jmp @@4
  305.  
  306. @@3:       xor AL, AL
  307.            stosb
  308.            loop @@2
  309.  
  310.          add SI, 319-Width
  311.          mov DI, SI
  312.          sub DI, 320
  313.          pop CX
  314.          loop @@1
  315.  
  316. @@4:   pop DS
  317.     end;
  318.  
  319. {
  320.   (* This was the original code I translated to assembler - JF *)
  321.  
  322.     For I:=XStart To XEnd Do
  323.     For J:=MinY To 199 Do
  324.     begin
  325.       V:=VMem[J, I];
  326.       If (V=0) Or
  327.          (V<Decay) Or
  328.          (I<=XStart) Or
  329.          (I>=XEnd) Then
  330.         Put(I, Pred(J), 0);
  331.       else
  332.         Put(I-Pred(Random(3)), Pred(J), V-Random(Decay));
  333.     end;
  334. }
  335.  
  336.     {Match?}
  337.     If (Random(150)=0) Or (Ch=' ') Then
  338.       FillChar(FlameArray[XStart+Random(XEnd-XStart-5)],5,255);
  339.  
  340.     {In-/Decrease?}
  341.     If (Ch='-') Then If MoreFire >-2 Then Dec(MoreFire);
  342.     If (Ch='+') Then If MoreFire < 4 Then Inc(MoreFire);
  343.  
  344.     {!!}
  345.     If UpCase(Ch) = 'C' Then FillChar(FlameArray,SizeOf(FlameArray),0);
  346.     If UpCase(Ch) = 'W' Then
  347.       for I:=1 To 10 Do FlameArray[XStart+Random(Width)]:=0;
  348.  
  349.     If Ch = '?' Then Help;
  350.  
  351.     if Ch in ['1'..'9'] Then FireIncrease:=3+Sqr(Ord(Ch)-Ord('1'));
  352.  
  353.     {This loop controls the "root" of the
  354.      flames ie. the values in FlameArray.}
  355.     For I:=XStart To XEnd Do
  356.     begin
  357.       X:=FlameArray[I];
  358.  
  359.       If X<MinFire Then { Increase by the "burnability"}
  360.       begin
  361.         {Starting to burn:}
  362.         If X>10 Then Inc(X,Random(FireIncrease));
  363.       end
  364.       else
  365.       { Otherwise randomize and increase by intensity (is burning)}
  366.         Inc(X,Rand(RootRand)+MoreFire);
  367.       If X>255 Then X:=255; { X Too large ?}
  368.       FlameArray[I]:=X;
  369.     end;
  370.  
  371.  
  372.     { Pour a little water on both sides of
  373.       the fire to make it look nice on the sides}
  374.     For I:=1 To Width Div 8 Do
  375.     begin
  376.       X:=Trunc(Sqr(Random)*Width/8);
  377.       FlameArray[XStart+X]:=0;
  378.       FlameArray[XEnd-X]:=0;
  379.     end;
  380.  
  381.     {Smoothen the values of FrameArray to avoid "descrete" flames}
  382.     P:=0;
  383.     For I:=XStart+Smooth To XEnd-Smooth Do
  384.     begin
  385.       X:=0;
  386.       For J:=-Smooth To Smooth Do Inc(X,FlameArray[I+J]);
  387.       FlameArray[I]:=X Div (2*Smooth+1);
  388.     end;
  389.   Until Ch=#27;
  390.   {Restore video mode}
  391.   R.Ax:=$0000+LastMode;
  392.   Intr($10,R);
  393.   {Good bye}
  394. end.